/********************************************************************************************************************************
 * 《C ++ Primer》第五版中文版，读书笔记：按照书中的的示例源码和每一个小章节的课后习题，自己动手写代码实现，作为联系和测试。
 * Date: 2024-03-26 18:17
 * Author: dimon.chen 
 * EMali: 1181302388@qq.com 
 * 
 * 章节: 第二章 变量和基本类型
 *       2.5.2 处理类型
 *             auto
 *             type alias 类型别名
 *             alias declarationi 别名声明: using 别名=基本数据类型
 *             typdef
 * 
 ********************************************************************************************************************************/


#include <iostream>

int main(int argc, char *argv[])
{
    ///
    /// 2.5.2 节练习
    /// 练习2.33 利用本节定义的变量，判断下列语句的运行结果
    ///

#if 0
    int i = 0, &r = i;              //i是int型, r是引用绑定到i，是i的别名
    auto a = r;                     //r引用作为初始值，r是i别名, i 为int型，a是int型

    const int ci = i, &cr = ci;     //ci是const int型，cr是常量引用，绑定到常量ci
    auto b = ci;                    //auto一般会忽略顶层const，从ci推演出的类型为 int , b是int型
    auto c = cr;                    //cr是ci的别名，ci是const int，从ci推演出来的类型为int, c是int型
    auto d = &i;                    //&i是 int *，d类型为 int *，指向int型的指针
    auto e = &ci;                   //&ci类型是 const int *，常量的地址是指向常量的指针, e 是const int *型


    const auto f = ci;              //ci的推演为int型（auto一般会忽略掉顶层const），f为const int型

    auto &g = ci;                   //初始值的引用定义时，顶层auto将会保留, g是常量引用，指向常量的引用，类型 
                                    //const int &
    //auto &h = 42;                 //错误：不允许普通的int型应用绑定到字面值
    const auto &j = 42;             //正确：允许常量引用绑定到字面值


    std::cout << "Before" << std::endl;
    std::cout << "a=" << a << " b=" << b << " c=" << c << std::endl;
    std::cout << "d=" << d << " e=" << e << " f=" << f << " g=" << g << " j=" << j << std::endl;


    std::cout << "After assign a,b,c," << std::endl;
    //a为整型对象，赋值为字面值42，a此时值为42
    a = 42;
    //b为整型对象，赋值为字面值42，b此时值为42
    b = 42;
    //c为整型对象，赋值为字面值42，c此时值为42
    c = 42;

    std::cout << "a=" << a << " b=" << b << " c=" << c << std::endl;
    std::cout << "d=" << d << " e=" << e << " f=" << f << " g=" << g << " j=" << j << std::endl;

    std::cout << "After assign d, e,f,g,h,j" << std::endl;
    //d为指向int的指针
    *d = 42;
    //e为指向整型常量的指针，e可以指向其他对象，但不能通过e修改它指向对象的值
    //e = 42;
    //g为常量引用，不同通过g来修改引用（绑定对象）的值
    //g = 42;


    std::cout << "a=" << a << " b=" << b << " c=" << c << std::endl;
    std::cout << "d=" << d << " e=" << e << " f=" << f << " g=" << g << " j=" << j << std::endl;
#endif



    ///
    /// 2.35 判断下列定义推断出的类型是什么，然后编写程序进行验证
    ///

    const int i = 42;           //i为整型常量，常量在定义时必须初始化
    auto j = i;                 //j为整型
    const auto &k = i;          //k为指向常量的引用，auto用于定义引用类型时顶层const将会保留
    auto *p = &i;               //p为指向整型常量的指针, p类型为 const int *。对常量取地址是一种底层const

    const auto j2 = i, &k2 = i; //i为顶层const 从i推断的类型为 int ，auto会忽略顶层const，j2为const int
                                //k2为指向整型常量的应用，类型为 const int & 

    j = 5;

    //k = 5;

    //*p = 5;

    j2 = 5;

    k2 = 5;


}